package com.gateway.security.authentication.convert;

import com.gateway.common.constant.Constants;
import com.gateway.common.dto.ApiDefinition;
import com.gateway.common.utils.Singleton;
import com.gateway.plugin.base.condition.data.CookieParameterData;
import com.gateway.plugin.base.condition.data.HeaderParameterData;
import com.gateway.plugin.base.condition.data.ParameterData;
import com.gateway.plugin.base.condition.data.ParameterDataFactory;
import com.gateway.plugin.base.condition.data.PostParameterData;
import com.gateway.plugin.base.condition.data.QueryParameterData;
import com.gateway.security.common.authentication.client.ClientAuthenticationToken;
import com.gateway.security.common.exception.TokenAuthenticationException;
import com.gateway.security.common.token.DefaultSecurityToken;
import com.gateway.security.common.token.ServerSecurityTokenRepository;
import com.gateway.security.config.SecurityConfig;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authentication.ServerAuthenticationConverter;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @program: api-gateway
 * @description:
 * @author: YuKai Fan
 * @create: 2025/2/10 23:05
 **/
public class ClientTokenAuthenticationConverter implements ServerAuthenticationConverter {

    private final ServerSecurityTokenRepository serverSecurityTokenRepository;

    public ClientTokenAuthenticationConverter(ServerSecurityTokenRepository serverSecurityTokenRepository) {
        this.serverSecurityTokenRepository = serverSecurityTokenRepository;
    }

    @Override
    public Mono<Authentication> convert(ServerWebExchange exchange) {
        ApiDefinition apiDefinition = exchange.getAttribute(Constants.API_DATA);
        assert apiDefinition != null;
        return this.serverSecurityTokenRepository.loadToken(exchange, apiDefinition)
                .switchIfEmpty(Mono.error(new TokenAuthenticationException("Authentication Error")))
                .flatMap(securityToken -> Mono.just(new ClientAuthenticationToken(securityToken, apiDefinition)));
    }
}
